/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package czStvDpds.graphics3D.gui;

import czStvDpds.graphics3D.GraphicsIndex;
import czStvDpds.graphics3D.TextureCreator;
import czStvDpds.graphics3D.geometry.Texture;
import czStvDpds.graphics3D.geometry.TextureProperties;
import czStvDpds.input.LWJGLKeyEvent;
import czStvDpds.logging.Logging;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import javax.imageio.ImageIO;
import org.lwjgl.input.Mouse;

/**
 * Textove policko, ktere uzivatel muze editovat. Pri zmacknuti ENTER generuje
 * udalost, jako kdyby byl zmacknut buttonek, a za command dosadi aktualni text
 *
 * @author Ondra
 */
public class LTextField extends LComponent {

    private String text;
    private int textX, textY;
    private String shownText;
    private boolean editing;
    private ArrayList<ButtonListener> listeners;
    private Texture basic, selected;
    private int maxTextWidth;
    private static final int OUTLINE = 10;

    public LTextField(String text) {
        super();
        super.model = new GUIObject(Modeler.generateTextFieldMesh(loc.getWidth(), loc.getHeight()));
        setText(text);
        recalculateMinSize();
        listeners = new ArrayList();
        editing = false;
        maxTextWidth = 0;

        createTextures();
        super.model.setTexture(basic);
    }

    public LTextField() {
        this("");
    }

    private void createTextures() {
        basic = new Texture();
        selected = new Texture();
        BufferedImage imgBasic = null;
        BufferedImage imgSelected = null;
        try {
            imgBasic = ImageIO.read(new File("resources/models/gui-textures/textfield-default.png"));
            imgSelected = ImageIO.read(new File("resources/models/gui-textures/textfield-selected.png"));
        } catch (IOException ex) {
            Logging.getMainLogger().log(Level.WARNING, "Failed to load texture: GUI.LTextfield, because of {0}", ex.getLocalizedMessage());
        }
        TextureProperties prop = new TextureProperties();
        prop.setType(TextureProperties.TEXTURE_2D);
        prop.setWidth(2);
        prop.setHeight(1);
        prop.setFilterMax(TextureProperties.FILTER_NEAREST);
        basic.setProperties(prop);
        basic.setData(TextureCreator.getImageData(imgBasic));
        selected.setProperties(prop);
        selected.setData(TextureCreator.getImageData(imgSelected));

        GraphicsIndex.getGLSynchronizer().generateTexture(basic);
        GraphicsIndex.getGLSynchronizer().generateTexture(selected);
    }

    @Override
    protected void model() {
        maxTextWidth = Modeler.ratioToPixels(loc.getWidth()) - (offset * 2) - (2 * OUTLINE);

        this.model.setPosition(loc.getX() + Modeler.pixelsToRatio(offset), loc.getY() + Modeler.pixelsToRatio(offset));
//        this.model.setText(shownText);
        this.model.setFont(font);
        //stanovovani pozice textu
        textX = /*
                 * ((Modeler.ratioToPixels(loc.getWidth()) -
                 * font.getWidth(shownText)) / 2)
                 */ OUTLINE;
        textY = ((Modeler.ratioToPixels(loc.getHeight()) - font.getHeight(shownText)) / 2);
//        this.model.setTextX(textX);
//        this.model.setTextY(textY);
        this.model.setText(TextPiece.cut(shownText, textX, textY, font));
        this.model.resize(Modeler.resizeTextFieldMesh(loc.getWidth() - (Modeler.pixelsToRatio(offset) * 2), loc.getHeight() - (Modeler.pixelsToRatio(offset) * 2)));
    }

    /**
     * nastavi text komponenty a podle toho i jeji velikost
     *
     * @param text
     */
    public final void setText(String text) {
        this.text = text;
        setShownText(editing ? text + "_" : text);
        recalculateMinSize();
    }

    private void setShownText(String shownText) {
        this.shownText = shownText;
        model.setText(TextPiece.cut(cropText(shownText), textX, textY, font));
    }

    /**
     * orezava text tak, aby se vesel do komponenty
     *
     * @param text - puvodni text
     * @return tak dlouhy text, aby se zobrazil spravne
     */
    private String cropText(String text) {
        if (font.getWidth(text) > maxTextWidth) {
            return cropText(text.substring(1));
        } else {
            return text;
        }
    }

    /**
     * ocividne vraci text komponenty
     *
     * @return text komponenty
     */
    public String getText() {
        return text;
    }

    /**
     * prida policku posluchac udalosti. Posluchac udalosti dostava do sve
     * metody buttonClicked() informace o tisku klavesy ENTER
     *
     * @param newListener novy posluchac
     */
    public void addButtonListener(ButtonListener newListener) {
        listeners.add(newListener);
    }

    /**
     * odebere dany posluchac ze seznamu posluchacu
     *
     * @param listener posluchac, ktery ma byt odebran
     */
    public void removeButtonListener(ButtonListener listener) {
        listeners.remove(listener);
    }

    /**
     * pokud je kliknuto na textfield, zahaji se editace textu
     */
    @Override
    protected void mousePressed() {
        if (!editing) {
            editing = true;
            setShownText(text + "_");
            model.setTexture(selected);
        }
    }

    @Override
    protected void mousePressedNotHere() {
        if (editing) {
            editing = false;
            setShownText(text);
            model.setTexture(basic);
        }
    }

    /**
     * pridavani/odebirani/uprava znaku
     *
     * @param e
     */
    @Override
    protected void keyPressed(LWJGLKeyEvent e) {
        if (editing) {
            if (e.getKey() == LWJGLKeyEvent.KEY_BACK) {
                if (text.length() > 0) {
                    text = text.substring(0, text.length() - 1);
                    setShownText(text + "_");
                }
            } else if (e.getKey() == LWJGLKeyEvent.KEY_RETURN) {
                editing = false;
                setShownText(text);
                model.setTexture(basic);
                generateEvent();
            } else if (e.getKey() == LWJGLKeyEvent.KEY_ESCAPE) {
                editing = false;
                model.setTexture(basic);
                setShownText(text);
            } else if (e.getCharakter() != '\0') {
                text = text.concat("" + e.getCharakter());
                setShownText(text + "_");
            }
//            remodel();
//            model.setText(shownText);
        }
    }

    /**
     * vygeneruje udalost a preda ji posluchacum
     */
    private void generateEvent() {
        for (ButtonListener listener : listeners.toArray(new ButtonListener[0])) {
            listener.buttonClicked(new ButtonEvent(this, text, Mouse.getX(), Mouse.getY()));
        }
    }

    @Override
    protected final void recalculateMinSize() {
        int textHeightPx = font.getHeight(shownText);
        int textWidthPx = font.getWidth(shownText);

        int minWidthPx = textWidthPx + (2 * OUTLINE);
        int minHeightPx = textHeightPx + (2 * OUTLINE);

        setMinSize(new ComponentPixelSize(minHeightPx, minWidthPx));

        if (parent != null) {
            parent.childChanged(this);
        }
    }

    @Override
    protected void mouseExited() {
        setShownText(text);
        editing = false;
        model.setTexture(basic);
    }

    @Override
    protected void mouseEntered() {
    }

    @Override
    protected void mouseReleased() {
    }
}
